//Copyright (c) 2006-2007 Microsoft Corporation.  All rights reserved
using System;
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;

using InvocationFramework.Common.Instrumentation;
using InvocationFramework.Common.Library;

using InvocationFramework.Adapters;
using InvocationFramework.Adapters.Inproc.Attributes;

namespace InvocationFramework.Adapters.Inproc.Transactions
{
    /// <summary>
    /// Permite ejecutar operaciones en un contexto transacional, ya sea usando COM+ 1.0 o COM+1.5
    /// </summary>
    /// <author>Rodolfo Finochietti 01/01/2006 11.37</author>
    internal static class TransactionDispatcher
    {
        #region Public members

        /// <summary>
        /// Ejecuta la operacion pasada por parametro en un contexto transaccional
        /// </summary>
        /// <param name="operDef">Definicion de la operacion a ejecutar</param>
        /// <param name="parameters">Parametros</param>
        /// <returns>Resultado de la ejecucion</returns>
        public static object Execute( OperationDefinition operDef, params object[] parameters )
        {
            object result = null;

            //Configura las opciones de la transaccion
            System.Transactions.TransactionOptions options = new System.Transactions.TransactionOptions( );
            options.IsolationLevel = GetIsolationLevel( operDef.TransactionIsolation );
            options.Timeout = operDef.TransactionTimeout;

            //Inicio la transacion
            using ( System.Transactions.TransactionScope scope = new System.Transactions.TransactionScope( GetScopeOption( operDef.TransactionType ), options ) )
            {

                //Ejecuto la operacion
                result = OperationExecutor.Execute( operDef, parameters );

                //Si la transaccion no se aborto la comiteo
                if ( System.Transactions.Transaction.Current != null && System.Transactions.Transaction.Current.TransactionInformation.Status != System.Transactions.TransactionStatus.Aborted )
                    scope.Complete( );
            }

            return result;
        }

        #endregion

        #region Private Methods

        [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes" )]
        private static System.Transactions.IsolationLevel GetIsolationLevel( InvocationFramework.Adapters.Inproc.Transactions.IsolationLevel level )
        {
            System.Transactions.IsolationLevel isolevel = System.Transactions.IsolationLevel.Serializable;

            try
            {
                if ( level != InvocationFramework.Adapters.Inproc.Transactions.IsolationLevel.Unspecified )
                    isolevel = ( System.Transactions.IsolationLevel )Enum.Parse( typeof( System.Transactions.IsolationLevel ), level.ToString( ) );
            }
            catch { }

            return isolevel;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes" )]
        private static System.Transactions.TransactionScopeOption GetScopeOption( InvocationFramework.Adapters.Inproc.Transactions.TransactionScope scope )
        {
            System.Transactions.TransactionScopeOption scopeOption = System.Transactions.TransactionScopeOption.Suppress;

            try
            {
                scopeOption = ( System.Transactions.TransactionScopeOption )Enum.Parse( typeof( System.Transactions.TransactionScopeOption ), scope.ToString( ) );
            }
            catch { }

            return scopeOption;
        }

        #endregion
    }
}